home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / mach / sun4c.md / iu_simulator.c < prev    next >
C/C++ Source or Header  |  1989-08-17  |  6KB  |  245 lines

  1. #ifdef sccsid
  2. static char     sccsid[] = "@(#)iu_simulator.c 1.6 88/03/03 SMI";
  3. #endif
  4.  
  5. /*
  6.  * Copyright (c) 1988 by Sun Microsystems, Inc.
  7.  */
  8.  
  9. /* Integer Unit simulator for Sparc FPU simulator. */
  10.  
  11. /*
  12.  * This whole file refuses to lint.
  13.  */
  14. #ifndef lint
  15. #include <sun4/fpu/fpu_simulator.h>
  16. #include <sun4/fpu/globals.h>
  17.  
  18. #define FPU_REG_FIELD unsigned_reg    /* Coordinate with FPU_REGS_TYPE. */
  19. #define FPU_FSR_FIELD unsigned_reg    /* Coordinate with FPU_FSR_TYPE. */
  20.  
  21. PRIVATE enum ftt_type
  22. fbcc(pinst, pregs, pfpu)
  23.     fp_inst_type    pinst;    /* FPU instruction to simulate. */
  24.     struct regs    *pregs;    /* Pointer to PCB image of registers. */
  25.     struct fpu     *pfpu;    /* Pointer to FPU register block. */
  26.  
  27. {
  28.     union {
  29.         fsr_type        fsr;
  30.         long            i;
  31.     }               klugefsr;
  32.     union {
  33.         fp_inst_type    fi;
  34.         int             i;
  35.     }               kluge;
  36.     enum fcc_type   fcc;
  37.     enum icc_type {
  38.         fbn, fbne, fblg, fbul, fbl, fbug, fbg, fbu,
  39.         fba, fbe, fbue, fbge, fbuge, fble, fbule, fbo
  40.     }               icc;
  41.  
  42.     unsigned        annul, takeit;
  43.  
  44.     klugefsr.i = pfpu->fpu_fsr;
  45.     fcc = klugefsr.fsr.fcc;
  46.     icc = (enum icc_type) (pinst.rd & 0xf);
  47.     annul = pinst.rd & 0x10;
  48.  
  49.     switch (icc) {
  50.     case fbn:
  51.         takeit = 0;
  52.         break;
  53.     case fbl:
  54.         takeit = fcc == fcc_less;
  55.         break;
  56.     case fbg:
  57.         takeit = fcc == fcc_greater;
  58.         break;
  59.     case fbu:
  60.         takeit = fcc == fcc_unordered;
  61.         break;
  62.     case fbe:
  63.         takeit = fcc == fcc_equal;
  64.         break;
  65.     case fblg:
  66.         takeit = (fcc == fcc_less) || (fcc == fcc_greater);
  67.         break;
  68.     case fbul:
  69.         takeit = (fcc == fcc_unordered) || (fcc == fcc_less);
  70.         break;
  71.     case fbug:
  72.         takeit = (fcc == fcc_unordered) || (fcc == fcc_greater);
  73.         break;
  74.     case fbue:
  75.         takeit = (fcc == fcc_unordered) || (fcc == fcc_equal);
  76.         break;
  77.     case fbge:
  78.         takeit = (fcc == fcc_greater) || (fcc == fcc_equal);
  79.         break;
  80.     case fble:
  81.         takeit = (fcc == fcc_less) || (fcc == fcc_equal);
  82.         break;
  83.     case fbne:
  84.         takeit = fcc != fcc_equal;
  85.         break;
  86.     case fbuge:
  87.         takeit = fcc != fcc_less;
  88.         break;
  89.     case fbule:
  90.         takeit = fcc != fcc_greater;
  91.         break;
  92.     case fbo:
  93.         takeit = fcc != fcc_unordered;
  94.         break;
  95.     case fba:
  96.         takeit = 1;
  97.         break;
  98.     }
  99.     if (takeit) {        /* Branch taken. */
  100.         int             tpc;
  101.  
  102.         kluge.fi = pinst;
  103.         tpc = pregs->r_pc;
  104.         if (annul && (icc == fba)) {    /* fba,a is wierd */
  105.             pregs->r_pc = tpc + (int) ((kluge.i << 10) >> 8);
  106.             pregs->r_npc = pregs->r_pc + 4;
  107.         } else {
  108.             pregs->r_pc = pregs->r_npc;
  109.             pregs->r_npc = tpc + (int) ((kluge.i << 10) >> 8);
  110.         }
  111.     } else {        /* Branch not taken. */
  112.         if (annul) {    /* Annul next instruction. */
  113.             pregs->r_pc = pregs->r_npc + 4;
  114.             pregs->r_npc += 8;
  115.         } else {    /* Execute next instruction. */
  116.             pregs->r_pc = pregs->r_npc;
  117.             pregs->r_npc += 4;
  118.         }
  119.     }
  120.     return (ftt_none);
  121. }
  122.  
  123. PRIVATE enum ftt_type
  124. fldst(pinst, pregs, pwindow, pfpu)
  125.     fp_inst_type    pinst;    /* FPU instruction to simulate. */
  126.     struct regs    *pregs;    /* Pointer to PCB image of registers. */
  127.     struct rwindow *pwindow;/* Pointer to locals and ins. */
  128.     struct fpu     *pfpu;    /* Pointer to FPU register block. */
  129.  
  130. /* Simulator for loads and stores between floating-point unit and memory. */
  131.  
  132. {
  133.     unsigned        nrs1, nrs2, nrd;    /* Register number fields. */
  134.     freg_type       f;
  135.     int             ea;
  136.     int             i;
  137.     union {
  138.         fp_inst_type    fi;
  139.         int             i;
  140.     }               kluge;
  141.     enum ftt_type   ftt;
  142.  
  143.     nrs1 = pinst.rs1;
  144.     nrs2 = pinst.rs2;
  145.     nrd = pinst.rd;
  146.     if (pinst.ibit == 0) {    /* effective address = rs1 + rs2 */
  147.         ftt = read_iureg(nrs1, pregs, pwindow, &ea);
  148.         if (ftt != ftt_none)
  149.             return (ftt);
  150.         ftt = read_iureg(nrs2, pregs, pwindow, &i);
  151.         if (ftt != ftt_none)
  152.             return (ftt);
  153.         ea += i;
  154.     } else {        /* effective address = rs1 + imm13 */
  155.         kluge.fi = pinst;
  156.         ea = (kluge.i << 19) >> 19;    /* Extract simm13 field. */
  157.         ftt = read_iureg(nrs1, pregs, pwindow, &i);
  158.         if (ftt != ftt_none)
  159.             return (ftt);
  160.         ea += i;
  161.     }
  162.  
  163.     fptrapaddr = (char *) ea;    /* setup bad addr in case we trap */
  164.     switch (pinst.op3 & 7) {
  165.     case 0:        /* LDF */
  166.         ftt = _fp_read_word((caddr_t) ea, &(f.int_reg));
  167.         if (ftt != ftt_none)
  168.             return (ftt);
  169.         pfpu->fpu_regs[nrd] = f.FPU_REG_FIELD;
  170.         break;
  171.     case 1:        /* LDFSR */
  172.         ftt = _fp_read_word((caddr_t) ea, &(f.int_reg));
  173.         if (ftt != ftt_none)
  174.             return (ftt);
  175.         pfpu->fpu_fsr = f.FPU_FSR_FIELD;
  176.         break;
  177.     case 3:        /* LDDF */
  178.         if ((ea & 0x7) != 0)
  179.             return (ftt_alignment);    /* Require double-alignment. */
  180.         ftt = _fp_read_word((caddr_t) ea, &(f.int_reg));
  181.         if (ftt != ftt_none)
  182.             return (ftt);
  183.         pfpu->fpu_regs[DOUBLE_E(nrd)] = f.FPU_REG_FIELD;
  184.         ftt = _fp_read_word((caddr_t) (ea + 4), &(f.int_reg));
  185.         if (ftt != ftt_none)
  186.             return (ftt);
  187.         pfpu->fpu_regs[DOUBLE_F(nrd)] = f.FPU_REG_FIELD;
  188.         break;
  189.     case 4:        /* STF */
  190.         f.FPU_REG_FIELD = pfpu->fpu_regs[nrd];
  191.         ftt = _fp_write_word((caddr_t) ea, f.int_reg);
  192.         if (ftt != ftt_none)
  193.             return (ftt);
  194.         break;
  195.     case 5:        /* STFSR */
  196.         f.FPU_FSR_FIELD = pfpu->fpu_fsr;
  197.         f.FPU_FSR_FIELD &= ~0x301000;    /* Clear reserved bits. */
  198.         f.FPU_FSR_FIELD |= 0x0E0000;    /* Set version number=7 . */
  199.         ftt = _fp_write_word((caddr_t) ea, f.int_reg);
  200.         if (ftt != ftt_none)
  201.             return (ftt);
  202.         break;
  203.     case 7:        /* STDF */
  204.         if ((ea & 0x7) != 0)
  205.             return (ftt_alignment);    /* Require double-alignment. */
  206.         f.FPU_REG_FIELD = pfpu->fpu_regs[DOUBLE_E(nrd)];
  207.         ftt = _fp_write_word((caddr_t) ea, f.int_reg);
  208.         if (ftt != ftt_none)
  209.             return (ftt);
  210.         f.FPU_REG_FIELD = pfpu->fpu_regs[DOUBLE_F(nrd)];
  211.         ftt = _fp_write_word((caddr_t) (ea + 4), f.int_reg);
  212.         if (ftt != ftt_none)
  213.             return (ftt);
  214.         break;
  215.     default:
  216.         fptrapaddr = (char *) pregs->r_pc;    /* addr of unimp inst */
  217.         return (ftt_unimplemented);
  218.     }
  219.  
  220.     pregs->r_pc = pregs->r_npc;    /* Do not retry emulated instruction. */
  221.     pregs->r_npc += 4;
  222.     return (ftt_none);
  223. }
  224.  
  225. /* PUBLIC FUNCTIONS */
  226.  
  227. enum ftt_type
  228. _fp_iu_simulator(pinst, pregs, pwindow, pfpu)
  229.     fp_inst_type    pinst;    /* FPU instruction to simulate. */
  230.     struct regs    *pregs;    /* Pointer to PCB image of registers. */
  231.     struct rwindow *pwindow;/* Pointer to locals and ins. */
  232.     struct fpu     *pfpu;    /* Pointer to FPU register block. */
  233.  
  234. {
  235.     switch (pinst.hibits) {
  236.     case 0:
  237.         return fbcc(pinst, pregs, pfpu);
  238.     case 3:
  239.         return fldst(pinst, pregs, pwindow, pfpu);
  240.     default:
  241.         return ftt_unimplemented;
  242.     }
  243. }
  244. #endif /* lint */
  245.